package com.hatricks.is.base.threadpool;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @packageName: com.hatricks.base.threadpool
 * @className: ThreadPoolTest
 * @author: yanyuhui yanyuhui@chinasofti.com
 * @date: 2022/6/7 8:13
 * @description:
 */
@Slf4j
public class ThreadPoolTest {

    // 手动创建一个线程池
    static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardPolicy());

    /**
     * 守护线程的生命周期和main方法的生命周期是一样的
     * 在停止的线程池的时候 只能是使用hook来进行等待线程池的执行结束
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
//        test01();

        Thread thread = new Thread(() -> {
//            while (true) {
            ThreadUtil.safeSleep(4000);
            log.info("线程1执行");
//            }
        });
        ExecutorService executorService = ThreadUtil.newExecutor();
        executorService.execute(thread);
        executorService.shutdown();
//        thread.setDaemon(true);
//        thread.start();
    }





    /**
     * 测试：不手动调用线程池shutdown方法，在线程池已经没有可运行的任务时JVM关闭会不会关闭线程池（即调用shutdown方法）
     */
    public static void test01() throws InterruptedException {
        // 通过添加钩子函数来阻塞JVM关闭过程，以便于打印出JVM关闭时线程池的状态
        addHook();

        executor.execute(() -> {
            while (true) {
                ThreadUtil.safeSleep(1000);
                System.out.println("我是子线程......");
            }
        });

        // 主线程阻塞在这里，等到子线程执行完毕后，我们关闭JVM
//        TimeUnit.SECONDS.sleep(30);
    }

    /**
     * 添加钩子
     */
    private static void addHook() {
        // 通过添加钩子函数来阻塞JVM关闭过程，以便于打印出JVM关闭时线程池的状态
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                System.out.println("钩子执行，等待 5s JVM正式关闭......");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("钩子函数睡眠被中断......");
            }
            executor.shutdown();
            // 打印线程池信息
            int retry = 10;
            try {
                while (retry > 0) {
                    if (!executor.awaitTermination(3, TimeUnit.SECONDS)) {
                        if (retry == 1) {
                            log.info("线程池非正常关闭");
                        }
                        retry--;
                        continue;
                    }
                    break;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("线程池信息 ：" + executor.toString());
        }));
    }


}
